/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/

package com.example.api.json.demo.config.apijson;

import apijson.Log;
import apijson.framework.APIJSONSQLExecutor;
import apijson.orm.SQLConfig;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * SQL 执行
 *
 * @author Lemon
 */
@Slf4j
public class DemoSQLExecutor extends APIJSONSQLExecutor {

    public static final String TAG = "DemoSQLExecutor";

    @Override
    protected Object getValue(SQLConfig config, ResultSet rs, ResultSetMetaData rsmd,
                              int tablePosition, JSONObject table, int columnIndex, String lable,
                              Map<String, JSONObject> childMap) throws Exception {
        // 脱敏
        maskColumn(table, "t_target_types", "channel_name", rsmd, columnIndex, lable);

        return super.getValue(config, rs, rsmd, tablePosition, table, columnIndex, lable, childMap);
    }


    private AtomicInteger columnIndexForMask = new AtomicInteger(-1);

    /**
     * 脱敏处理，maskValue为脱敏后字段自行定义
     *
     * @param table      处理的值
     * @param tableName  表名
     * @param columnName 字段名
     * @throws SQLException /
     */
    private void maskColumn(JSONObject table, String tableName, String columnName,
                            ResultSetMetaData rsmd, int columnIndex, String lable) throws SQLException {
        // 判断表名
        if (tableName.equals(rsmd.getTableName(1))) {
            if (columnName.equals(lable)) {
                columnIndexForMask.set(columnIndex);
                columnIndexForMask.incrementAndGet();
            }
            // 字段脱敏
            if (columnIndex == columnIndexForMask.get()) {
                log.info("oldValue to mask,{}", table.getString(columnName));
                String maskValue = "*";
                table.put(columnName, maskValue);
                // 恢复
                columnIndexForMask.set(-1);
            }
        }
    }

    @Override
    public Connection getConnection(SQLConfig config) throws Exception {
        Log.d(TAG, "getConnection  config.getDatasource() = " + config.getDatasource());

        String key = config.getDatasource() + "-" + config.getDatabase();
        Connection c = connectionMap.get(key);
        if (c == null || c.isClosed()) {
            try {
                connectionMap.put(key, DataSourceConfig.DATA_SOURCE_HIKARICP.getConnection());
            } catch (Exception e) {
                Log.e(TAG, "getConnection   try { "
                        + "DataSource ds = DemoApplication.getApplicationContext().getBean(DataSource.class); .."
                        + "} catch (Exception e) = " + e.getMessage());
            }
        }

        // 必须最后执行 super 方法，因为里面还有事务相关处理。
        // 如果这里是 return c，则会导致 增删改 多个对象时只有第一个会 commit，即只有第一个对象成功插入数据库表
        return super.getConnection(config);
    }

    /**
     * oracle 需要指定事务级别
     */
    @Override
    public int getTransactionIsolation() {
        return 2;
//        return super.getTransactionIsolation();
    }
}
